package br.pucrio.inf.serializer;

import br.pucrio.inf.services.TamderaGrammarAccess;
import br.pucrio.inf.tamdera.ConceptDeclaration;
import br.pucrio.inf.tamdera.ConstraintSetDeclaration;
import br.pucrio.inf.tamdera.DependencyRuleDeclaration;
import br.pucrio.inf.tamdera.MetricConstraint;
import br.pucrio.inf.tamdera.NameClassMapping;
import br.pucrio.inf.tamdera.PackageMapping;
import br.pucrio.inf.tamdera.ParentMapping;
import br.pucrio.inf.tamdera.PrefixMapping;
import br.pucrio.inf.tamdera.RegExpressionMapping;
import br.pucrio.inf.tamdera.RulesSpecification;
import br.pucrio.inf.tamdera.SuffixMapping;
import br.pucrio.inf.tamdera.TamderaPackage;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.serializer.acceptor.ISemanticSequenceAcceptor;
import org.eclipse.xtext.serializer.acceptor.SequenceFeeder;
import org.eclipse.xtext.serializer.diagnostic.ISemanticSequencerDiagnosticProvider;
import org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic.Acceptor;
import org.eclipse.xtext.serializer.sequencer.AbstractSemanticSequencer;
import org.eclipse.xtext.serializer.sequencer.GenericSequencer;
import org.eclipse.xtext.serializer.sequencer.ISemanticNodeProvider.INodesForEObjectProvider;
import org.eclipse.xtext.serializer.sequencer.ISemanticSequencer;
import org.eclipse.xtext.serializer.sequencer.ITransientValueService;
import org.eclipse.xtext.serializer.sequencer.ITransientValueService.ValueTransient;

@SuppressWarnings("restriction")
public class AbstractTamderaSemanticSequencer extends AbstractSemanticSequencer {

	@Inject
	protected TamderaGrammarAccess grammarAccess;
	
	@Inject
	protected ISemanticSequencerDiagnosticProvider diagnosticProvider;
	
	@Inject
	protected ITransientValueService transientValues;
	
	@Inject
	@GenericSequencer
	protected Provider<ISemanticSequencer> genericSequencerProvider;
	
	protected ISemanticSequencer genericSequencer;
	
	
	@Override
	public void init(ISemanticSequencer sequencer, ISemanticSequenceAcceptor sequenceAcceptor, Acceptor errorAcceptor) {
		super.init(sequencer, sequenceAcceptor, errorAcceptor);
		this.genericSequencer = genericSequencerProvider.get();
		this.genericSequencer.init(sequencer, sequenceAcceptor, errorAcceptor);
	}
	
	public void createSequence(EObject context, EObject semanticObject) {
		if(semanticObject.eClass().getEPackage() == TamderaPackage.eINSTANCE) switch(semanticObject.eClass().getClassifierID()) {
			case TamderaPackage.CONCEPT_DECLARATION:
				if(context == grammarAccess.getConceptDeclarationRule() ||
				   context == grammarAccess.getParagraphRule()) {
					sequence_ConceptDeclaration(context, (ConceptDeclaration) semanticObject); 
					return; 
				}
				else break;
			case TamderaPackage.CONSTRAINT_SET_DECLARATION:
				if(context == grammarAccess.getConstraintSetDeclarationRule() ||
				   context == grammarAccess.getParagraphRule()) {
					sequence_ConstraintSetDeclaration(context, (ConstraintSetDeclaration) semanticObject); 
					return; 
				}
				else break;
			case TamderaPackage.DEPENDENCY_RULE_DECLARATION:
				if(context == grammarAccess.getDependencyRuleDeclarationRule() ||
				   context == grammarAccess.getParagraphRule()) {
					sequence_DependencyRuleDeclaration(context, (DependencyRuleDeclaration) semanticObject); 
					return; 
				}
				else break;
			case TamderaPackage.METRIC_CONSTRAINT:
				if(context == grammarAccess.getConstraintRule() ||
				   context == grammarAccess.getMetricConstraintRule()) {
					sequence_MetricConstraint(context, (MetricConstraint) semanticObject); 
					return; 
				}
				else break;
			case TamderaPackage.NAME_CLASS_MAPPING:
				if(context == grammarAccess.getConceptMapRule() ||
				   context == grammarAccess.getNameClassMappingRule()) {
					sequence_NameClassMapping(context, (NameClassMapping) semanticObject); 
					return; 
				}
				else break;
			case TamderaPackage.PACKAGE_MAPPING:
				if(context == grammarAccess.getConceptMapRule() ||
				   context == grammarAccess.getPackageMappingRule()) {
					sequence_PackageMapping(context, (PackageMapping) semanticObject); 
					return; 
				}
				else break;
			case TamderaPackage.PARENT_MAPPING:
				if(context == grammarAccess.getConceptMapRule() ||
				   context == grammarAccess.getParentMappingRule()) {
					sequence_ParentMapping(context, (ParentMapping) semanticObject); 
					return; 
				}
				else break;
			case TamderaPackage.PREFIX_MAPPING:
				if(context == grammarAccess.getConceptMapRule() ||
				   context == grammarAccess.getPrefixMappingRule()) {
					sequence_PrefixMapping(context, (PrefixMapping) semanticObject); 
					return; 
				}
				else break;
			case TamderaPackage.REG_EXPRESSION_MAPPING:
				if(context == grammarAccess.getConceptMapRule() ||
				   context == grammarAccess.getRegExpressionMappingRule()) {
					sequence_RegExpressionMapping(context, (RegExpressionMapping) semanticObject); 
					return; 
				}
				else break;
			case TamderaPackage.RULES_SPECIFICATION:
				if(context == grammarAccess.getRulesSpecificationRule()) {
					sequence_RulesSpecification(context, (RulesSpecification) semanticObject); 
					return; 
				}
				else break;
			case TamderaPackage.SUFFIX_MAPPING:
				if(context == grammarAccess.getConceptMapRule() ||
				   context == grammarAccess.getSuffixMappingRule()) {
					sequence_SuffixMapping(context, (SuffixMapping) semanticObject); 
					return; 
				}
				else break;
			}
		if (errorAcceptor != null) errorAcceptor.accept(diagnosticProvider.createInvalidContextOrTypeDiagnostic(semanticObject, context));
	}
	
	/**
	 * Constraint:
	 *     (name=ID conceptMapper=ConceptMap? constraints+=Constraint* referredConstraintSets+=[ConstraintSetDeclaration|ID]*)
	 */
	protected void sequence_ConceptDeclaration(EObject context, ConceptDeclaration semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (name=ID constraints+=Constraint*)
	 */
	protected void sequence_ConstraintSetDeclaration(EObject context, ConstraintSetDeclaration semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (
	 *         (source=[ConceptDeclaration|ID] type=DependencyType relation=DependencyRelation target=[ConceptDeclaration|ID]) | 
	 *         (source=[ConceptDeclaration|ID] type=OnlyCanDependencyType relation=DependencyRelation target=[ConceptDeclaration|ID])
	 *     )
	 */
	protected void sequence_DependencyRuleDeclaration(EObject context, DependencyRuleDeclaration semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (metric=Metric operator=OPERATOR value=Value)
	 */
	protected void sequence_MetricConstraint(EObject context, MetricConstraint semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, TamderaPackage.Literals.METRIC_CONSTRAINT__METRIC) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, TamderaPackage.Literals.METRIC_CONSTRAINT__METRIC));
			if(transientValues.isValueTransient(semanticObject, TamderaPackage.Literals.METRIC_CONSTRAINT__OPERATOR) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, TamderaPackage.Literals.METRIC_CONSTRAINT__OPERATOR));
			if(transientValues.isValueTransient(semanticObject, TamderaPackage.Literals.METRIC_CONSTRAINT__VALUE) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, TamderaPackage.Literals.METRIC_CONSTRAINT__VALUE));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getMetricConstraintAccess().getMetricMetricParserRuleCall_0_0(), semanticObject.getMetric());
		feeder.accept(grammarAccess.getMetricConstraintAccess().getOperatorOPERATORTerminalRuleCall_1_0(), semanticObject.getOperator());
		feeder.accept(grammarAccess.getMetricConstraintAccess().getValueValueParserRuleCall_2_0(), semanticObject.getValue());
		feeder.finish();
	}
	
	
	/**
	 * Constraint:
	 *     nameOfClass=STRING
	 */
	protected void sequence_NameClassMapping(EObject context, NameClassMapping semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, TamderaPackage.Literals.NAME_CLASS_MAPPING__NAME_OF_CLASS) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, TamderaPackage.Literals.NAME_CLASS_MAPPING__NAME_OF_CLASS));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getNameClassMappingAccess().getNameOfClassSTRINGTerminalRuleCall_0_1_0(), semanticObject.getNameOfClass());
		feeder.finish();
	}
	
	
	/**
	 * Constraint:
	 *     packageName=QualifiedName
	 */
	protected void sequence_PackageMapping(EObject context, PackageMapping semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, TamderaPackage.Literals.PACKAGE_MAPPING__PACKAGE_NAME) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, TamderaPackage.Literals.PACKAGE_MAPPING__PACKAGE_NAME));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getPackageMappingAccess().getPackageNameQualifiedNameParserRuleCall_0_1_0(), semanticObject.getPackageName());
		feeder.finish();
	}
	
	
	/**
	 * Constraint:
	 *     parent=QualifiedName
	 */
	protected void sequence_ParentMapping(EObject context, ParentMapping semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, TamderaPackage.Literals.PARENT_MAPPING__PARENT) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, TamderaPackage.Literals.PARENT_MAPPING__PARENT));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getParentMappingAccess().getParentQualifiedNameParserRuleCall_0_1_0(), semanticObject.getParent());
		feeder.finish();
	}
	
	
	/**
	 * Constraint:
	 *     prefixName=STRING
	 */
	protected void sequence_PrefixMapping(EObject context, PrefixMapping semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, TamderaPackage.Literals.PREFIX_MAPPING__PREFIX_NAME) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, TamderaPackage.Literals.PREFIX_MAPPING__PREFIX_NAME));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getPrefixMappingAccess().getPrefixNameSTRINGTerminalRuleCall_0_1_0(), semanticObject.getPrefixName());
		feeder.finish();
	}
	
	
	/**
	 * Constraint:
	 *     regExpression=STRING
	 */
	protected void sequence_RegExpressionMapping(EObject context, RegExpressionMapping semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, TamderaPackage.Literals.REG_EXPRESSION_MAPPING__REG_EXPRESSION) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, TamderaPackage.Literals.REG_EXPRESSION_MAPPING__REG_EXPRESSION));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getRegExpressionMappingAccess().getRegExpressionSTRINGTerminalRuleCall_0_1_0(), semanticObject.getRegExpression());
		feeder.finish();
	}
	
	
	/**
	 * Constraint:
	 *     paragraphs+=Paragraph*
	 */
	protected void sequence_RulesSpecification(EObject context, RulesSpecification semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     suffixName=STRING
	 */
	protected void sequence_SuffixMapping(EObject context, SuffixMapping semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, TamderaPackage.Literals.SUFFIX_MAPPING__SUFFIX_NAME) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, TamderaPackage.Literals.SUFFIX_MAPPING__SUFFIX_NAME));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getSuffixMappingAccess().getSuffixNameSTRINGTerminalRuleCall_0_1_0(), semanticObject.getSuffixName());
		feeder.finish();
	}
}
